package liecai_class.day07;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池 - 创建
 *
 * 线程是一个很沉重的对象，创建和销毁都需要消耗大量的资源
 * 如果频繁的创建和销毁线程，效率非常低下，影响性能
 * 因此，线程池的概念被提了出来
 * 线程池就是一个容器，里面存放着很多线程
 * 当我们需要使用线程时，就从线程池中获取一个线程使用
 * 使用完毕后，不是销毁线程，而是将线程归还给线程池
 * 这样当再需要线程是，可以再池中获取到线程，实现了线程的复用，减少了线程创建销毁的次数，提高了性能
 * 因此，线程池在并发编程中非常的重要，也是面试中的一个热点
 *
 * JUC库中提供了一个线程池类：ExecutorService - ThreadPoolExecutor
 *
 * ThreadPoolExecutor构造参数详解:
 *  线程池创建时，并不会立即创建线程
 *  此时如果有任务提交，则无论线程池中是否有闲置的线程，都会创建一个新的线程来执行任务
 *  直到线程池中管理的线程数达到corePoolSize个
 *  之后，再有任务提交，就不会创建新的线程，而是将任务放入到一个任务队列中
 *  当线程池中有空闲线程时，就会从任务队列中取出任务来执行
 *  如果任务队列中的任务都被取出来执行了，此时再有任务提交，就会创建新的线程来执行任务
 *  如果来的任务非常的多，所有线程都在忙，队列也被填满了，此时再有任务提交，就会创建新的线程来执行任务
 *  但无论如何，线程池中管理的线程的数量都不能超过maximumPoolSize个
 *  如果线程池中线程数已经达到了maximumPoolSize个，所有线程都在忙，队列也被填满了
 *  此时再有任务提交，就会拒绝服务助手进行拒绝
 *  任务高峰期过去后，线程开始闲置，一旦闲置超过了keepAliveTime，线程就会被销毁
 *  但无论怎么销毁，线程池中管理的线程的数量都不能小于corePoolSize个
 */
public class Demo01 {
    public static void main(String[] args) throws InterruptedException {
        // 创建线程池对象
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5),
                new RejectedExecutionHandler() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        System.out.println("###线程池过于繁忙，拒绝服务###"+r);
                    }
                }
        );

        System.out.println(pool);

//        for(int i = 1;i<100;i++){
//            pool.execute(new Runnable() {
//                @Override
//                public void run() {
//                    while(true){}
//                }
//            });
//            System.out.println("任务"+i+"提交成功");
//            System.out.println(pool);
//            Thread.sleep(1000);
//        }

        for(int i = 1;i<=20;i++){
            Thread.sleep(100);
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000 * 10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("任务执行完毕"+this);
                }
            });
            System.out.println("任务"+i+"提交成功");
        }

        while(true){
            System.out.println(pool);
            Thread.sleep(1000);
        }

    }
}
